﻿using Kugar.Core.ExtMethod;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Kugar.Core.Log;
using Kugar.Core.Web;
using Kugar.Core.Web.Controllers;
using Kugar.Web.Wechat;
using Kugar.Web.Wechat.Entities;
using Kugar.Web.Wechat.Enums;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Routing;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Senparc.Weixin;
using Senparc.Weixin.Exceptions;
using Senparc.Weixin.MP;
using Senparc.Weixin.MP.AdvancedAPIs;
using Senparc.Weixin.MP.AdvancedAPIs.OAuth;
using Senparc.Weixin.MP.Entities.Request;

namespace Kugar.Web.Wechat.MP
{
    /// <summary>
    /// 公众号回调的Controller
    /// </summary>

    public class MPCallbackController : Controller
    {

        public MPCallbackController( )
        {
        }

        [AllowAnonymous]
        [Route("Core/MPCallback/Callback")]
        public async Task<ActionResult> Callback([FromServices] IMPOAuthWithSchemeHandler handler, [FromQuery] string code, [FromQuery] string state)
        {
            if (code == "" || state == "")
            {
                return Content("无效code");

                return Unauthorized();// new HttpUnauthorizedResult("已取消授权登陆");
            }

            var stateData = "";


            if (HttpContext.Session.TryGetValue(state, out var tmpBytes))
            {
                stateData = Encoding.UTF8.GetString(tmpBytes).ToStringEx();// Session[state].ToStringEx();
            }
            else
            {
                return Content("无效的state");
            }

            if (string.IsNullOrWhiteSpace(stateData))
            {
                return Content("state错误");

                return Unauthorized();
            }


            var json = JObject.Parse(stateData);

            var scope = (WechatOAuthScope)(int)json["Scope"];
            var backUrl = json.GetString("BackUrl");
            var appID = json.GetString("AppID");
            var appserect = json.GetString("AppSecret");

            OAuthAccessTokenResult oauthUser = null;

            try
            {
                oauthUser = OAuthApi.GetAccessToken(appID, appserect, code);
            }
            catch (ErrorJsonResultException e)
            {
                if (e.JsonResult.ErrorCodeValue == 40163)
                {
                    return Redirect(backUrl);
                }
                else
                {
                    LoggerManager.Default.Error("微信登录回调错误:", e);
                    return Content($"微信登录回调错误:{e.JsonResult.errmsg},{e.JsonResult.ErrorCodeValue}");
                }

            }
            catch (Exception e)
            {
                LoggerManager.Default.Error("微信登录GetAccessToken错误:", e);
                return Redirect(backUrl);
            }



            var user = new WechatUserOAuth
            {
                OpenID = oauthUser.openid,
                UnionID = oauthUser.unionid,
                Scope = scope,
                AccessToken = oauthUser.access_token,
                RefreshToken = oauthUser.refresh_token
            };


            if (scope == WechatOAuthScope.snsapi_userinfo)
            {
                var wxUser = await OAuthApi.GetUserInfoAsync(oauthUser.access_token, oauthUser.openid);

                user.NickName = wxUser.nickname;
                user.HeaderPortraitUrl = wxUser.headimgurl;

            }

            HttpContext.Session.SetString("WechatMPUser", JsonConvert.SerializeObject(user));


            var scheme = json.GetString("Scheme");

            var values=await handler.OnWechatAuthorityCallbackAsync(appID, user, scheme);

            (string key, string value)[] data = new []
            {
                ("wechat_appID", appID.ToStringEx()),
                ("wechat_openID", user.OpenID.ToStringEx()),
                ("wechat_scope", ((int)user?.Scope).ToStringEx()),
                ("wechat_nickname", user.NickName.ToStringEx()),
                ("wechat_unionId", user.UnionID.ToStringEx())
            };
            
            if (values.HasData())
            {
                data = data.Concat(values).ToArrayEx();
            }

            var token = this.BuildJWtToken(user.OpenID.ToStringEx(),
                "",
                data
                );

            
            Response.Cookies.Append($"WechatMP-{scheme}", token, new CookieOptions() { Expires = DateTimeOffset.Now.AddDays(7), SameSite = SameSiteMode.None });

            

            return Redirect(backUrl);
        }

        [Route("Core/MPCallback/service")]
        [HttpGet]
        public async Task<IActionResult> Service([FromServices] IMPOAuthWithSchemeHandler handler, string signature, [FromQuery] string timestamp, [FromQuery] string nonce, [FromQuery] string echostr)
        {
            if (handler == null)
            {
                return Content("请先注册微信公众号服务");
            }

            LoggerManager.Default.Debug($"微信调用:signature={signature},timestamp={timestamp},nonce={nonce},echostr={echostr}");

            var appID = Request.HttpContext.GetRouteValue("AppID").ToStringEx();

            if (string.IsNullOrWhiteSpace(appID))
            {
                return Content("AppID不能为空");
            }

            var wechat =await handler.GetMPInfoByAppID(appID);

            if (CheckSignature.Check(signature, timestamp, nonce, wechat.token))
            {
                return Content(echostr); //返回随机字符串则表示验证通过
            }
            else
            {
                return Content("failed:" + signature + "," + CheckSignature.GetSignature(timestamp, nonce, wechat.token) + "。" +
                               "如果你在浏览器中看到这句话，说明此地址可以被作为微信公众账号后台的Url，请注意保持Token一致。");
            }
            


            return null;
        }

        [Route("Core/MPCallback/service")]
        [ActionName("Service")]
        [HttpPost]
        public async Task<IActionResult> ServicePost([FromServices] IWechatMP mp, [FromBody]PostModel postModel)
        {
            var wechat = mp.GetWechatItemByAppID(postModel.AppId);

            if (!CheckSignature.Check(postModel.Signature, postModel.Timestamp, postModel.Nonce, wechat.token))
            {
                return Content("参数错误！");
            }

            // v4.2.2之后的版本，可以设置每个人上下文消息储存的最大数量，防止内存占用过多，如果该参数小于等于0，则不限制
            var maxRecordCount = 10;

            Request.EnableBuffering();

            //自定义MessageHandler，对微信请求的详细判断操作都在这里面。
            var inputStream = Request.Body;
            inputStream.Position = 0;

            

            var messageHandler = new WeiXinMessageHandler(mp, inputStream, postModel, maxRecordCount);

            messageHandler.OmitRepeatedMessage = true;//启用消息去重功能


            //Exception error = null;
            //DateTime startDt=DateTime.Now;

            try
            {
                //执行微信处理过程
                await messageHandler.ExecuteAsync(default);

                var response = messageHandler.ResponseDocument.ToStringEx();

                return Content(response, "application/xml");

                //return new FixWeixinBugWeixinResult(messageHandler.ResponseDocument.ToStringEx());
            }
            catch (Exception ex)
            {

                //error = ex;

                //using (TextWriter tw = new StreamWriter(Server.MapPath("~/App_Data/Error_" + DateTime.Now.Ticks + ".txt")))
                //{
                //    tw.WriteLine(ex.Message);
                //    tw.WriteLine(ex.InnerException.Message);
                //    if (messageHandler.ResponseDocument != null)
                //    {
                //        tw.WriteLine(messageHandler.ResponseDocument.ToString());
                //    }
                //    tw.Flush();
                //    tw.Close();
                //}
            }
            finally
            {

                //if (WebBLL.IsDebugging)
                //{
                //    WebBLL.TraceLog.AddWeiXinMessageLog(
                //        WebBLL.Platform.CurrentPlatformID,
                //        WebBLL.Customer.CurrentCustomerID.Value,
                //        oauthID.ToObjectId(),
                //        messageHandler.RequestMessage.FromUserName,
                //        messageHandler.RequestMessage.ToUserName,
                //        startDt,
                //        messageHandler.RequestDocument.ToStringEx(),
                //        messageHandler.ResponseDocument.ToStringEx(),
                //        error
                //        );
                //}
            }

            return Content("");

        }

        [Route("Core/MP/DefaultUserLogin/{scheme}")]
        public ActionResult DefaultUserLogin()
        {
            var schemeName = Request.GetString("scheme");

            if (string.IsNullOrWhiteSpace(schemeName))
            {
                if (RouteData.Values.TryGetValue("scheme", out var tmp))
                {
                    schemeName = tmp.ToStringEx();
                }
            }

            if (string.IsNullOrWhiteSpace(schemeName))
            {
                return Content("scheme为空");
            }

            return null;
        }
    }


}
